namespace Sustainalytics.Portfolios.Service.Models
{
    using Sustainalytics.Entities;
    using Sustainalytics.Portfolios.BL;
    using Sustainalytics.Utils;
    using System;
    using System.Linq;

    public class FullDetailsPortfolioFactory : PortfolioDtoFactory
    {
        private readonly ISubscribeToPortfolioManagement _subscriptionManagement;

        public FullDetailsPortfolioFactory(ISubscribeToPortfolioManagement subscriptionManagement)
        {
            this._subscriptionManagement = subscriptionManagement;
        }

        public override PortfolioBase Create(Portfolio portfolio, string createdByUsername)
        {
            return new PortfolioDto
            {
                Id = portfolio.Id,
                Name = portfolio.Name,
                DataCreated = portfolio.DataCreated,
                DateModified = portfolio.DateModified,
                AddedByFullName = portfolio.AddedByFullName,
                AddedByUserId = portfolio.AddedByUserId,
                AddedByUserName = portfolio.AddedByUserName.ToLowerInvariant(),
                Details = GetPortfolioDetails(portfolio),
                CompanyCount = portfolio.CompanyCount,
                SharingStatus = portfolio.SharingStatus,
                IsSystemPortfolio = portfolio.IsSystemPortfolio(),
                IsReadonly = portfolio.IsReadonly,
                IsMyPortfolio = IsMyPortfolio(portfolio, createdByUsername),
                HasSubscription = this.HasSubscription(portfolio)
            };
        }

        private static string GetPortfolioDetails(Portfolio portfolio)
        {
            if (portfolio.IsSystemPortfolio())
            {
                var systemPortfolio = portfolio as SystemPortfolio;
                if (systemPortfolio != null)
                {
                    return systemPortfolio.RelatedUniverses.Select(x => x.Name).Aggregate((i, j) => i + ", " + j);
                }
            }

            return string.Empty;
        }

        private static bool IsMyPortfolio(Entities.PortfolioBase portfolio, string createdByUsername)
        {
            return string.Equals(
                createdByUsername,
                portfolio.AddedByUserName,
                StringComparison.InvariantCultureIgnoreCase);
        }

        private bool HasSubscription(Entities.PortfolioBase portfolio)
        {
            return !portfolio.AccountIds.IsNullOrEmpty()
                   && this._subscriptionManagement.UserHasSubscriptionToPortfolio(
                       portfolio.Id,
                       portfolio.AddedByUserId,
                       portfolio.AccountIds);
        }
    }
}
